;(function () {
  const originalFetch = window.fetch
  const reportedErrors = new Map() // 用 Map 来存储错误记录

  const CACHE_DURATION = 5 * 60 * 1000 // 5 分钟

  window.fetch = async function (...args) {
    const [resource, config] = args
    const request = new Request(resource, config)
    const requestId = `${request.method} ${request.url}`

    const requestInfo = {
      method: request.method,
      url: request.url,
      headers: [...request.headers.entries()],
      body: request.body,
    }

    try {
      const response = await originalFetch.apply(this, args)
      const clonedResponse = response.clone()
      const responseBody = await clonedResponse.text()
      const responseData = {
        status: response.status,
        statusText: response.statusText,
        headers: [...response.headers.entries()],
        body: responseBody,
      }

      if (!response.ok && !isRecentlyReported(requestId)) {
        reportError('Fetch Error', requestInfo, responseData)
        markReported(requestId)
      }

      return response
    } catch (error) {
      if (!isRecentlyReported(requestId)) {
        reportError('Fetch Network Error', requestInfo, { error: error.message })
        markReported(requestId)
      }
      throw error
    }
  }

  const originalXhr = window.XMLHttpRequest

  function WrappedXhr() {
    const xhr = new originalXhr()
    const requestInfo = {}
    let requestId

    xhr.open = function (method, url, ...args) {
      requestInfo.method = method
      requestInfo.url = url
      requestId = `${method} ${url}`
      originalXhr.prototype.open.apply(this, arguments)
    }

    xhr.setRequestHeader = function (header, value) {
      if (!requestInfo.headers) {
        requestInfo.headers = []
      }
      requestInfo.headers.push([header, value])
      originalXhr.prototype.setRequestHeader.apply(this, arguments)
    }

    xhr.send = function (body) {
      requestInfo.body = body

      xhr.addEventListener('loadend', async function () {
        let responseBody
        try {
          switch (xhr.responseType) {
            case '':
            case 'text':
              responseBody = xhr.responseText
              break
            case 'json':
              responseBody = JSON.stringify(xhr.response)
              break
            case 'blob':
              responseBody = await blobToText(xhr.response)
              break
            default:
              responseBody = 'Unsupported responseType: ' + xhr.responseType
          }
        } catch (error) {
          responseBody = 'Error parsing response: ' + error.message
        }

        const responseData = {
          status: xhr.status,
          statusText: xhr.statusText,
          headers: parseHeaders(xhr.getAllResponseHeaders()),
          body: responseBody,
        }

        if ((xhr.status < 200 || xhr.status >= 400) && !isRecentlyReported(requestId)) {
          reportError('XHR Error', requestInfo, responseData)
          markReported(requestId)
        }
      })

      xhr.addEventListener('error', function () {
        if (!isRecentlyReported(requestId)) {
          reportError('XHR Network Error', requestInfo, { error: xhr.statusText })
          markReported(requestId)
        }
      })

      originalXhr.prototype.send.call(this, body)
    }

    return xhr
  }

  window.XMLHttpRequest = WrappedXhr

  function parseHeaders(rawHeaders) {
    return rawHeaders
      .trim()
      .split(/[\r\n]+/)
      .map((line) => line.split(': '))
      .reduce((acc, [key, value]) => {
        acc[key] = value
        return acc
      }, {})
  }

  async function blobToText(blob) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader()
      reader.onload = () => resolve(reader.result)
      reader.onerror = reject
      reader.readAsText(blob)
    })
  }

  // 检查请求是否在缓存时间内已被记录
  function isRecentlyReported(requestId) {
    const timestamp = reportedErrors.get(requestId)
    if (!timestamp) return false
    // 检查是否在5分钟之内
    return Date.now() - timestamp < CACHE_DURATION
  }

  // 标记请求为已记录
  function markReported(requestId) {
    reportedErrors.set(requestId, Date.now())
    // 设置定时器在一定时间后移除记录
    setTimeout(() => reportedErrors.delete(requestId), CACHE_DURATION)
  }
  // 设备解析器
  const deviceInfo = new UAParser().getResult()

  function getAdditionalInfo() {
    const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection
    const connectionType = connection ? connection.effectiveType : 'unknown'
    const screenWidth = window.screen.width
    const screenHeight = window.screen.height
    return {
      device: {
        screenSize: screenWidth + 'x' + screenHeight,
        online: navigator.onLine,
        connectionType,
        ...deviceInfo,
      },
      referrer: document.referrer,
      currentUrl: window.location.href,
      userAgent: navigator.userAgent,
    }
  }

  // 错误信息上报函数
  function reportError(type, request, response) {
    const additionalInfo = getAdditionalInfo()
    const errorData = {
      type,
      target: request.url,
      request,
      response,
      timestamp: new Date().toISOString(),
      ...additionalInfo,
    }
    // 以下可以替换为实际的上报错误的逻辑，比如发送请求到后台。
    const zkdtMonitorData = window.zkdtMonitor ? window.zkdtMonitor.data : {}
    const paylod = {
      userId: zkdtMonitorData.userId || '',
      userName: zkdtMonitorData.userName || '',
      proID: zkdtMonitorData.proID || '6',
      proVersion: zkdtMonitorData.proVersion || '',
      env: zkdtMonitorData.env || 'pro',
      // errType: errorData.type,
      errType: 2,
      page: errorData.currentUrl,
      content: JSON.stringify(errorData),
    }
    fetch('https://gateway.matefarm.net/v3/config/statistic/add', {
      method: 'POST',
      body: JSON.stringify(paylod),
      headers: { 'Content-Type': 'application/json' },
    }).catch()
  }
})()
